From 438fad803e4d97c1ef4b6507b3f08913ae0e0c17 Mon Sep 17 00:00:00 2001 From: Philip Zander Date: Wed, 12 Jan 2022 21:31:21 +0100 Subject: [PATCH] gdkkeys-win32: Fix crash when keyboard DLL failed to load DLL loading failures should not happen under normal circumstances, but we should at least try not to crash and and print better diagnostic messages if they do happen. See https://gitlab.gnome.org/GNOME/gtk/-/issues/4610 --- gdk/win32/gdkkeys-win32-impl.c | 9 ++++-- gdk/win32/gdkkeys-win32.c | 58 ++++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/gdk/win32/gdkkeys-win32-impl.c b/gdk/win32/gdkkeys-win32-impl.c index 4baf9201b3..b5640633b2 100644 --- a/gdk/win32/gdkkeys-win32-impl.c +++ b/gdk/win32/gdkkeys-win32-impl.c @@ -180,7 +180,8 @@ keystate_to_modbits (GdkWin32KeymapLayoutInfo *info, BYTE result = 0; int i; - g_return_val_if_fail (tables != NULL, 0); + if (tables == NULL) + return 0; vk_to_bit = tables->pCharModifiers.ptr->pVkToBit.ptr; @@ -198,7 +199,8 @@ modbits_to_level (GdkWin32KeymapLayoutInfo *info, PKBDTABLES tables = (PKBDTABLES) info->tables; PMODIFIERS modifiers; - g_return_val_if_fail (tables != NULL, 0); + if (tables == NULL) + return 0; modifiers = tables->pCharModifiers.ptr; if (modbits > modifiers->wMaxModBits) @@ -268,7 +270,8 @@ vk_to_char_fuzzy (GdkWin32KeymapLayoutInfo *info, if (is_dead) *is_dead = FALSE; - g_return_val_if_fail (tables != NULL, WCH_NONE); + if (tables == NULL) + return WCH_NONE; wch_tables = tables->pVkToWcharTable.ptr; diff --git a/gdk/win32/gdkkeys-win32.c b/gdk/win32/gdkkeys-win32.c index 43de7eb7d6..f41f267997 100644 --- a/gdk/win32/gdkkeys-win32.c +++ b/gdk/win32/gdkkeys-win32.c @@ -181,6 +181,7 @@ get_keyboard_layout_file (const char *layout_name) DWORD file_name_len = 0; int dir_len = 0; int buf_len = 0; + LSTATUS status; static const char prefix[] = "SYSTEM\\CurrentControlSet\\Control\\" "Keyboard Layouts\\"; @@ -189,18 +190,32 @@ get_keyboard_layout_file (const char *layout_name) g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s", prefix, layout_name); - if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0, - KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) - goto fail1; + + status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0, + KEY_QUERY_VALUE, &hkey); + if (status != ERROR_SUCCESS) + { + g_warning("Could not open registry key '%s'. Error code: %d", + kbdKeyPath, (int)status); + goto fail1; + } /* Get sizes */ - if (RegQueryValueExA (hkey, "Layout File", 0, &var_type, 0, - &file_name_len) != ERROR_SUCCESS) - goto fail2; + status = RegQueryValueExA (hkey, "Layout File", 0, &var_type, 0, + &file_name_len); + if (status != ERROR_SUCCESS) + { + g_warning("Could not query registry key '%s\\Layout File'. Error code: %d", + kbdKeyPath, (int)status); + goto fail2; + } dir_len = GetSystemDirectoryA (0, 0); /* includes \0 */ if (dir_len == 0) - goto fail2; + { + g_warning("GetSystemDirectoryA failed. Error: %d", (int)GetLastError()); + goto fail2; + } /* Allocate buffer */ buf_len = dir_len + (int) strlen ("\\") + file_name_len; @@ -214,10 +229,12 @@ get_keyboard_layout_file (const char *layout_name) result[dir_len - 1] = '\\'; /* Append file name */ - if (RegQueryValueExA (hkey, "Layout File", 0, &var_type, - (LPBYTE) &result[dir_len], &file_name_len) - != ERROR_SUCCESS) - goto fail3; + status = RegQueryValueExA (hkey, "Layout File", 0, &var_type, + (LPBYTE) &result[dir_len], &file_name_len); + if (status != ERROR_SUCCESS) + { + goto fail3; + } result[dir_len + file_name_len] = '\0'; @@ -415,6 +432,9 @@ gdk_keysym_to_key_entry_index (GdkWin32KeymapLayoutInfo *info, gunichar c; gintptr index; + if (info->reverse_lookup_table == NULL) + return -1; + /* Special cases */ if (sym == GDK_KEY_Tab) return VK_TAB; @@ -439,8 +459,6 @@ gdk_keysym_to_key_entry_index (GdkWin32KeymapLayoutInfo *info, /* Try converting to Unicode and back */ c = gdk_keyval_to_unicode (sym); - g_return_val_if_fail (info->reverse_lookup_table != NULL, -1); - index = -1; if (g_hash_table_lookup_extended (info->reverse_lookup_table, GINT_TO_POINTER (c), @@ -537,7 +555,7 @@ update_keymap (GdkWin32Keymap *keymap) info->file = get_keyboard_layout_file (info->name); - if (load_layout_dll (keymap, info->file, info)) + if (info->file != NULL && load_layout_dll (keymap, info->file, info)) { info->key_entries = g_array_new (FALSE, FALSE, sizeof (GdkWin32KeymapKeyEntry)); @@ -546,6 +564,11 @@ update_keymap (GdkWin32Keymap *keymap) g_direct_equal); init_vk_lookup_table (keymap, info); } + else + { + g_warning("Failed to load keyboard layout DLL for layout %s: %s", + info->name, info->file); + } } if (info->handle == current_layout) @@ -978,6 +1001,13 @@ gdk_win32_keymap_translate_keyboard_state (GdkKeymap *gdk_keymap, if (consumed_modifiers) *consumed_modifiers = mod_bits_to_gdk_mod_mask (consumed_mod_bits); + /* Just a diagnostic message to inform the user why their keypresses aren't working. + * Shouldn't happen under normal circumstances. */ + if (tmp_keyval == GDK_KEY_VoidSymbol && layout_info->tables == NULL) + g_warning("Failed to translate keypress (keycode: %u) for group %d (%s) because " + "we could not load the layout.", + hardware_keycode, group, layout_info->name); + return tmp_keyval != GDK_KEY_VoidSymbol; } -- 2.30.2